package org.jeecg.modules.common.baseservice.impl;


//import cn.hutool.core.lang.func.LambdaUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.LambdaUtils;
import com.baomidou.mybatisplus.core.toolkit.support.ColumnCache;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableName;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.TableFieldInfo;
import com.baomidou.mybatisplus.core.metadata.TableInfo;
import com.baomidou.mybatisplus.core.metadata.TableInfoHelper;

import org.apache.ibatis.logging.Log;
import org.apache.ibatis.logging.LogFactory;
import org.jeecg.common.util.oConvertUtils;
import org.jeecg.modules.common.baseservice.IBaseBatchService;
import org.jeecg.modules.common.utils.BeanObjUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.lang.reflect.Array;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;

/**
 * 实体对象批量处理类
 */
@Service
public class BaseBatchServiceImp<T> implements IBaseBatchService<T> {

    protected Log log = LogFactory.getLog(getClass());



    public BeanObjUtil beanObjUtil;


    /**
     * 根据ids和一个对象，批量更新复制属性给ids对应的数据
     * @param ids
     * @param entityObj
     * @return
     */
    @Override
    public UpdateWrapper batchCopyUpdateByArray(Object[] ids, T entityObj)  {

        UpdateWrapper<T> updateWrapper = new UpdateWrapper<T>();
        updateWrapper.in("id", ids); // 设置需要更新的字段
        return getBatchSqlUpdateByObj(updateWrapper,entityObj,null);
    }
    /**
     * 根据ids和一个对象，批量更新复制属性给ids对应的数据
     * @param ids
     * @param entityObj
     * @return
     */
    @Override
    public UpdateWrapper batchCopyUpdateByList(List ids, T entityObj) {

        UpdateWrapper<T> updateWrapper = new UpdateWrapper<>();
        updateWrapper.in("id", ids); // 设置需要更新的字段
        return getBatchSqlUpdateByObj(updateWrapper,entityObj,null);
    }


    /**
     * 按对象属性有无值动态获得查询sql。即对象属性有值的列被查询。过滤对象属性有值则加入过滤条件
     * @param queryWrapper
     * @param selectEntityObj select查询跳进，，属性有值则查询显示，属性无值则忽略
     * @param whereEntityObj  where过滤条件对象，属性有值则过滤，属性无值则忽略
     * @return
     */
    @Override
    public QueryWrapper<T> getQuerySqlByObj(QueryWrapper<T> queryWrapper, T selectEntityObj, T whereEntityObj){
        List<Field> selectFieldList = oConvertUtils.isNotEmpty( selectEntityObj) ? beanObjUtil.getAllField(selectEntityObj.getClass()) : null;
        if(oConvertUtils.listIsNotEmpty(selectFieldList)) {
            for (Field fieldOne : selectFieldList
            ) {
                String fieldName = fieldOne.getName();
                Object fieldValue = beanObjUtil.getFieldValueByName(selectEntityObj, fieldName);
                //动态获取表名对应的属性列名
                String columnName = getColumnNameByField(selectEntityObj.getClass(),fieldOne);
                if (oConvertUtils.isNotEmpty(fieldValue) && oConvertUtils.isNotEmpty(columnName) ) {
                    queryWrapper.select(columnName);
                }
            }
        }

        List<Field> wherefieldlist = oConvertUtils.isNotEmpty( whereEntityObj) ? beanObjUtil.getAllField(whereEntityObj.getClass()) : null;
        if(oConvertUtils.listIsNotEmpty(wherefieldlist)) {
            for (Field fieldOne : wherefieldlist
            ) {
                String fieldName = fieldOne.getName();
                Object fieldValue = beanObjUtil.getFieldValueByName(whereEntityObj, fieldName);
                //动态获取表名对应的属性列名
                String columnName = oConvertUtils.isNotEmpty(fieldValue) ? getColumnNameByField(whereEntityObj.getClass(),fieldOne) : null;
                if (oConvertUtils.isNotEmpty(fieldValue) && oConvertUtils.isNotEmpty(columnName)  ) {
                    if ( fieldValue instanceof String && "is not null".equals(fieldValue.toString())) {
                        queryWrapper.isNotNull(columnName);
                    } else if ( fieldValue instanceof String && "is null".equals(fieldValue.toString())) {
                        queryWrapper.isNull(columnName);
                    } else if ( fieldValue instanceof String && fieldValue.toString().indexOf(">") == 0) {
                        queryWrapper.gt(columnName, fieldValue.toString().substring(1));
                    } else if ( fieldValue instanceof String && fieldValue.toString().indexOf("<") == 0) {
                        queryWrapper.lt(columnName, fieldValue.toString().substring(1));
                    } else if ( fieldValue instanceof String && fieldValue.toString().indexOf(">=") == 0) {
                        queryWrapper.ge(columnName, fieldValue.toString().substring(2));
                    } else if ( fieldValue instanceof String && fieldValue.toString().indexOf("<=") == 0) {
                        queryWrapper.le(columnName, fieldValue.toString().substring(2));
                    }
                    //多值条件几乎无法用到
                    else  if (fieldValue instanceof List && oConvertUtils.listIsNotEmpty((List) fieldValue)) {
                        queryWrapper.in(columnName, fieldValue); // list多个值使用in过滤条件
                    }else if ( fieldValue != null && fieldValue.getClass().isArray() && Array.getLength(fieldValue) >0 ) {
                        queryWrapper.in(columnName, fieldValue); // 数组Array多个值使用in过滤条件
                    }
                    else{
                        queryWrapper.eq(columnName,fieldValue);
                    }
                }
            }
        }

        return queryWrapper;

    }

    /**
     * 动态获取查询sql，指定返回数据属性列名称，where过滤条件map
     * @param queryWrapper
     * @param entityClazz 对象类名
     * @param selectFields 指定返回数据属性列名称
     * @param whereCondition where过滤条件map
     * @return
     */
    @Override
    public QueryWrapper<T> getQuerySqlByMap(QueryWrapper<T> queryWrapper, Class entityClazz, Collection<String> selectFields, Map whereCondition){
        //拼接select条件
        for (String keyFieldName : selectFields
        ) {
            //动态获取表名对应的属性列名
            String columnName = oConvertUtils.isNotEmpty( keyFieldName) ? getColumnNameByFieldName(entityClazz,keyFieldName) : null;
            if(oConvertUtils.isNotEmpty( columnName) ) {
                queryWrapper.select(columnName);
            }
        }

        //拼接where条件
        if(oConvertUtils.isNotEmpty(whereCondition)) {
            for (Object keyFieldNameOne : whereCondition.keySet()
            ) {
                String keyFieldName = keyFieldNameOne.toString();
                keyFieldName = keyFieldName.replace(">", "").replace("<", "").replace("=", "");
                Object conditionValue = whereCondition.get(keyFieldName);
                //动态获取表名对应的属性列名
                String columnName = oConvertUtils.isNotEmpty(conditionValue) ? getColumnNameByFieldName(entityClazz, keyFieldName) : null;

                if (oConvertUtils.isNotEmpty(columnName) && oConvertUtils.isNotEmpty(conditionValue)) {
                    if (conditionValue instanceof List && oConvertUtils.listIsNotEmpty((List) conditionValue)) {
                        queryWrapper.in(columnName, conditionValue); // list多个值使用in过滤条件
                    } else if (conditionValue != null && conditionValue.getClass().isArray() && Array.getLength(conditionValue) > 0) {
                        queryWrapper.in(columnName, conditionValue); // 数组Array多个值使用in过滤条件
                    } else if (conditionValue instanceof String && conditionValue.toString().indexOf(",") >= 0) {
                        queryWrapper.in(columnName, conditionValue.toString().split(","));
                    } else if (conditionValue instanceof String && "is not null".equals(conditionValue.toString())) {
                        queryWrapper.isNotNull(columnName);
                    } else if (conditionValue instanceof String && "is null".equals(conditionValue.toString())) {
                        queryWrapper.isNull(columnName);
                    } else if (conditionValue instanceof String && conditionValue.toString().indexOf(">") == 0) {
                        queryWrapper.gt(columnName, conditionValue.toString().substring(1));
                    } else if (conditionValue instanceof String && conditionValue.toString().indexOf("<") == 0) {
                        queryWrapper.lt(columnName, conditionValue.toString().substring(1));
                    } else if (conditionValue instanceof String && conditionValue.toString().indexOf(">=") == 0) {
                        queryWrapper.ge(columnName, conditionValue.toString().substring(2));
                    } else if (conditionValue instanceof String && conditionValue.toString().indexOf("<=") == 0) {
                        queryWrapper.le(columnName, conditionValue.toString().substring(2));
                    } else {
                        queryWrapper.eq(columnName, conditionValue);
                    }
                }
            }
        }

        return queryWrapper;

    }

    /**
     * 获取批量处理的sql语句,set对象属性有值部分会被set无值属性被忽略，wher过滤对象有值属性加入过滤条件
     * @param updateWrapper
     * @param setEntityObj  set条件对象，属性有值则set，属性无值则忽略
     * @param whereEntityObj where过滤条件，属性有值则加入过滤条件，属性无值则忽略
     * @return
     */
    @Override
    public UpdateWrapper<T> getBatchSqlUpdateByObj(UpdateWrapper<T> updateWrapper, T setEntityObj, T whereEntityObj){
        List<Field> setfieldlist = oConvertUtils.isNotEmpty( setEntityObj) ? beanObjUtil.getAllField(setEntityObj.getClass()) : null;
        if(oConvertUtils.listIsNotEmpty(setfieldlist)) {
            for (Field fieldOne : setfieldlist
            ) {
                String fieldName = fieldOne.getName();
                Object fieldValue = beanObjUtil.getFieldValueByName(setEntityObj, fieldName);
                //动态获取表名对应的属性列名
                String columnName = getColumnNameByField(setEntityObj.getClass(),fieldOne);
                if (oConvertUtils.isNotEmpty(fieldValue) && oConvertUtils.isNotEmpty(columnName) ) {
                    if ( fieldValue instanceof String && ( "null".equals(fieldValue.toString()) || "is null".equals(fieldValue.toString())) ) {
                        updateWrapper.set(columnName,null);
                    }else{
                        updateWrapper.set(columnName, fieldValue);
                    }

                }
            }
        }

        List<Field> wherefieldlist = oConvertUtils.isNotEmpty( whereEntityObj) ? beanObjUtil.getAllField(whereEntityObj.getClass()) : null;
        if(oConvertUtils.listIsNotEmpty(wherefieldlist)) {
            for (Field fieldOne : wherefieldlist
            ) {
                String fieldName = fieldOne.getName();
                Object fieldValue = beanObjUtil.getFieldValueByName(whereEntityObj, fieldName);
                //动态获取表名对应的属性列名
                String columnName = oConvertUtils.isNotEmpty(fieldValue) ? getColumnNameByField(whereEntityObj.getClass(),fieldOne) : null;
                if (oConvertUtils.isNotEmpty(fieldValue) && oConvertUtils.isNotEmpty(columnName)  ) {
                    updateWrapper.eq(columnName, fieldValue);
                }
            }
        }

        return updateWrapper;

    }

    /**
     *
     * @param updateWrapper
     * @param entityClazz
     * @param setFieldMap set设置属性列map
     * @param whereCondition where过滤体条件map
     * @return
     */
    @Override
    public UpdateWrapper getBatchSqlUpdateByMap(UpdateWrapper updateWrapper, Class entityClazz, Map setFieldMap, Map whereCondition){
        if(oConvertUtils.isNotEmpty(setFieldMap)) {
            //拼接set条件
            for (Object keyFieldNameOne : setFieldMap.keySet()
            ) {
                String keyFieldName = keyFieldNameOne.toString();
                Object newFieldValue = setFieldMap.get(keyFieldName);
                //动态获取表名对应的属性列名
                String columnName = oConvertUtils.isNotEmpty(newFieldValue) ? getColumnNameByFieldName(entityClazz, keyFieldName) : null;

                if (oConvertUtils.isNotEmpty(columnName) && oConvertUtils.isNotEmpty(newFieldValue)) {
                    if (newFieldValue instanceof String && ("null".equals(newFieldValue.toString()) || "is null".equals(newFieldValue.toString()))) {
                        updateWrapper.set(columnName, null);
                    } else {
                        updateWrapper.set(columnName, newFieldValue);
                    }
                }
            }
        }

        //拼接where条件
        if(oConvertUtils.isNotEmpty(whereCondition)) {
            for (Object keyFieldNameOne : whereCondition.keySet()
            ) {
                String keyFieldName = keyFieldNameOne.toString();
                Object conditionValue = whereCondition.get(keyFieldName);
                //动态获取表名对应的属性列名
                String columnName = oConvertUtils.isNotEmpty(conditionValue) ? getColumnNameByFieldName(entityClazz, keyFieldName) : null;

                if (oConvertUtils.isNotEmpty(columnName) && oConvertUtils.isNotEmpty(conditionValue)) {
                    if (conditionValue instanceof List && oConvertUtils.listIsNotEmpty((List) conditionValue)) {
                        updateWrapper.in(columnName, conditionValue); // list多个值使用in过滤条件
                    } else if (conditionValue != null && conditionValue.getClass().isArray() && Array.getLength(conditionValue) > 0) {
                        updateWrapper.in(columnName, conditionValue); // 数组Array多个值使用in过滤条件
                    } else if (conditionValue instanceof String && "is not null".equals(conditionValue.toString())) {
                        updateWrapper.isNotNull(columnName);
                    } else if (conditionValue instanceof String && "is null".equals(conditionValue.toString())) {
                        updateWrapper.isNull(columnName);
                    } else if (conditionValue instanceof String && conditionValue.toString().indexOf(">") == 0) {
                        updateWrapper.gt(columnName, conditionValue.toString().substring(1));
                    } else if (conditionValue instanceof String && conditionValue.toString().indexOf("<") == 0) {
                        updateWrapper.lt(columnName, conditionValue.toString().substring(1));
                    } else if (conditionValue instanceof String && conditionValue.toString().indexOf(">=") == 0) {
                        updateWrapper.ge(columnName, conditionValue.toString().substring(2));
                    } else if (conditionValue instanceof String && conditionValue.toString().indexOf("<=") == 0) {
                        updateWrapper.le(columnName, conditionValue.toString().substring(2));
                    } else {
                        updateWrapper.eq(columnName, conditionValue);
                    }
                }
            }
        }

        return updateWrapper;

    }



    /**
     * 批量复制对象属性值给指定过滤条件的对象
     * @param whereCondition where过滤条件 筛选目标对象
     * @param entityObject 需要被复制的源对象
     * @return
     */
    @Override
    public UpdateWrapper<T> batchCopyUpdateByWhereMap(Map<String, Object> whereCondition, T entityObject) {

        UpdateWrapper<T> updateWrapper = new UpdateWrapper<>();
        if(oConvertUtils.isNotEmpty(whereCondition)) {
            for (Object keyFieldNameOne : whereCondition.keySet()
            ) {
                String keyFieldName = keyFieldNameOne.toString();
                Object conditionValue = whereCondition.get(keyFieldName);
                //动态获取表名对应的属性列名
                String columnName = oConvertUtils.isNotEmpty(conditionValue) ? getColumnNameByFieldName(entityObject.getClass(), keyFieldName) : null;

                if (oConvertUtils.isNotEmpty(columnName) && oConvertUtils.isNotEmpty(conditionValue)) {
                    if (conditionValue instanceof List && oConvertUtils.listIsNotEmpty((List) conditionValue)) {
                        updateWrapper.in(columnName, conditionValue); // list多个值使用in过滤条件
                    } else if (conditionValue != null && conditionValue.getClass().isArray() && Array.getLength(conditionValue) > 0) {
                        updateWrapper.in(columnName, conditionValue); // 数组Array多个值使用in过滤条件
                    } else if (conditionValue instanceof String && "is not null".equals(conditionValue.toString())) {
                        updateWrapper.isNotNull(columnName);
                    } else if (conditionValue instanceof String && "is null".equals(conditionValue.toString())) {
                        updateWrapper.isNull(columnName);
                    } else if (conditionValue instanceof String && conditionValue.toString().indexOf(">") == 0) {
                        updateWrapper.gt(columnName, conditionValue.toString().substring(1));
                    } else if (conditionValue instanceof String && conditionValue.toString().indexOf("<") == 0) {
                        updateWrapper.lt(columnName, conditionValue.toString().substring(1));
                    } else if (conditionValue instanceof String && conditionValue.toString().indexOf(">=") == 0) {
                        updateWrapper.ge(columnName, conditionValue.toString().substring(2));
                    } else if (conditionValue instanceof String && conditionValue.toString().indexOf("<=") == 0) {
                        updateWrapper.le(columnName, conditionValue.toString().substring(2));
                    } else {
                        updateWrapper.eq(columnName, conditionValue);
                    }
                }
            }
        }
        return getBatchSqlUpdateByObj(updateWrapper,entityObject,null);
    }

    /**
     * 批量删除指定对象，把满足过滤条件的对象删除掉
     * @param whereCondition   过滤条件
     * @param objClazz   对象类型
     * @return
     */
    @Override
    public UpdateWrapper batchDeleteByWhereMap(Map whereCondition, Class objClazz){

        UpdateWrapper<T> updateWrapper = new UpdateWrapper<>();
        
        return getBatchSqlUpdateByMap(updateWrapper,objClazz,null,whereCondition);
    }


    public  String getColumnNameByFieldName(Class clazz, String fieldName) {
        //动态获取表名对应的属性列名
        Field fieldOne = beanObjUtil.getFieldByName(clazz, fieldName);
        return getColumnNameByField(clazz,fieldOne);
    }

    public  String getColumnNameByField(Class entityClass,Field fieldOne) {
//        TableField tableFieldAnnotation = fieldOne.getAnnotation(TableField.class);
//        String columnName = (tableFieldAnnotation != null && tableFieldAnnotation.value() != null)
//                ? tableFieldAnnotation.value()
//                : null;

//        TableInfo tableInfo = TableInfoHelper.getTableInfo(entityClass);
//        if (tableInfo != null && tableInfo.getFieldInfoMap() != null) {
//            Map<String, TableFieldInfo> fieldInfoMap = tableInfo.getFieldInfoMap();
//            TableFieldInfo fieldInfo = fieldInfoMap.get(property);
//            if (fieldInfo != null) {
//                return fieldInfo.getColumnName();
//            }
//        }

        //获取实体所有对应的列
        Map<String, ColumnCache> columnMap = LambdaUtils.getColumnMap(entityClass);
        //hutool包，获取实体属性名称
//        String fieldName = LambdaUtils.getFieldName(TestEntity::getPullName);
        //通过属性名获取对应的列名
        String columnName = oConvertUtils.isNotEmpty( columnMap.get(LambdaUtils.formatKey(fieldOne.getName())) ) ? columnMap.get(LambdaUtils.formatKey(fieldOne.getName())).getColumn() : null;

        return columnName;
    }
    /**
     * 获取所有的数据库列名
     * @param entityClass
     * @return
     */

    public  List<String> getColumnNames(Class entityClass) {
        List<String> columnNames = new ArrayList<>();
        TableName tableNameAnnotation = (TableName) entityClass.getAnnotation(TableName.class);
        String tableName = (tableNameAnnotation != null) ? tableNameAnnotation.value() : null;

        Field[] fields = entityClass.getDeclaredFields();
        for (Field field : fields) {
            TableField tableFieldAnnotation = field.getAnnotation(TableField.class);
            if (tableFieldAnnotation != null && !tableFieldAnnotation.exist()) {
                continue; // 忽略不存在的字段
            }
            String columnName = (tableFieldAnnotation != null && tableFieldAnnotation.value() != null)
                    ? tableFieldAnnotation.value()
                    : field.getName();
            columnNames.add(columnName);
        }

        return columnNames;
    }
}
